<ui:composition template="/WEB-INF/templates/showcase.xhtml"
	xmlns="http://www.w3.org/1999/xhtml"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:o="http://omnifaces.org/ui"
>
	<ui:define name="description">
		<p>
			The <code>&lt;o:cache&gt;</code> component allows to cache a fragment of rendered markup. The first
			request for a page that has this component on it will cause this markup to be put into the cache. Then
			for subsequent requests the cached content is used directly and none of the components, backing beans
			and services that were used to generate this content in the first place will be consulted.
		</p>
		<p>
			Caching can take place in application scope, or in session scope. For individual fragments a
			time can be specified for which the cached content is valid. After this time is elapsed, the very
			first request to the page containing the cache component in question will cause new content to be 
			rendered and put into the cache. A default time can be set per scope in web.xml.
		</p>
		<p>
			For each scope a maximum capacity can be set. If the capacity for that scope is exceeded, an element will be
			removed following a least recently used policy (LRU).
		</p>
		<p>
			Via a cache provider mechanism an alternative cache implementation can be configured in web.xml. The default
			cache is based on <a href="http://code.google.com/p/concurrentlinkedhashmap">http://code.google.com/p/concurrentlinkedhashmap</a>.
		</p>
	</ui:define>

	<ui:define name="demo">
		<p>
			<b>Now:</b> #{now}
		</p>

		<hr/>
		
		<h3>Example 1 - Fixed cache</h3>
		<p>
			The following renders a couple of items in a default cache, which means the session scope is used without a timeout. 
			On the first page refresh, all items should have the same time as indicated by "<code>Now</code>" above.
			After a page refresh the time of the items should stay constant, indicating cached content is used. 
		</p>
		<p>
			<o:cache key="firstCache" reset="#{cacheBean.reset}">
				<h:dataTable value="#{cacheBean.items}" var="item">
					<h:column>
						<i>#{item}</i> <br/>
					</h:column>
				</h:dataTable>
			</o:cache>
  		</p>

  		<hr/>
  		<br/>
  		
  		<h3>Example 2 - Timed cache</h3>
  		<p>
			The following renders a time-stamp in the session scoped cache, for which a time to live has been set to 15 seconds.
			On the first page refresh, it should be equal again to the time as indicated by "<code>Now</code>" above. 
			For page refreshes done within 15 seconds after this first request it should be constant. After this time, 
			it should change into the "<code>Now</code>" time again, meaning a timeout took place and new content was rendered.
		</p>
		<p>
			<o:cache time="15">
				<i>Session scope content valid for 15 seconds generated at: #{now}</i>
			</o:cache>
  		</p>

  		<hr/>
  		<br/>
  		
  		<h3>Example 3 - Treshold on number of cached items</h3>
  		<p>
  			The following renders a time-stamp in the session scoped cache again, this time using an explicit and dynamic key.
  			For this show case application, the number of items in the session cache has been set to <code>4</code>
  			using the following setting in <code>web.xml</code>:
  		</p>
		<pre>
&lt;context-param&gt;
    &lt;param-name&gt;org.omnifaces.CACHE_SETTING_SESSION_MAX_CAPACITY&lt;/param-name&gt;
    &lt;param-value&gt;6&lt;/param-value&gt;
&lt;/context-param&gt;
  		</pre>
  		<p>
  			Since 4 items have been used already by the other examples, only 2 more fit it.
  		</p>
  		<p>
  			This can be demonstrated by generating cache items via the numbered buttons shown below. 
  			Clicking on any two of the same numbers below will switch between the cached content for those
  			and will keep showing the time-stamp associated with them on their first click. 
  			Upon clicking a third number, and then clicking the number of the original 2 that was clicked the
  			longest time ago (except 0, the default), a new time-stamp will be associated with that.
  		</p>
  		<p>
  			This means the threshold of 6 cached items had been exceeded and the last accessed item was evicted. 
  		</p>
  		<p>
  			E.g. click 0, click 1, click 0 (notice it has the same time-stamp), click 1 (same timestamp), 
  			click 2, click 1 (gets new time-stamp)
  		</p>
		<h:form>
			Set Cache key to: 
			<h:commandButton action="#{cacheBean.setKey(0)}" value="0" />, 
			<h:commandButton action="#{cacheBean.setKey(1)}" value="1" />, 
			<h:commandButton action="#{cacheBean.setKey(2)}" value="2" />, 
			<h:commandButton action="#{cacheBean.setKey(3)}" value="3" />
		</h:form>
		<p>
			<o:cache key="test-#{cacheBean.key}">
				<i>Session scope content for key #{cacheBean.key} generated at: #{now}</i>
			</o:cache>
  		</p>
  		
  		<hr/>
  		<br/>
  		
  		<h3>Example 4 - Explicitly resetting/expiring cache</h3>
  		<p>
  			Cached data may need to be reset at the point that the underlying data is known to have changed. Any cache
  			entry can be programmatically removed based on the scope and the key of this entry. By default the cache
  			component generates an internal key, but this can be overridden by using an explicit key. The default scope is "session". 
  		</p>
  		<p>
  			Cached data can also be reset via the <code>reset</code> attribute on the <code>cache</code> component. Using this method
  			it's not necessary to know the scope and key of the cache. Instead, the attribute can be bound to a property of a backing bean
  			which can return <code>true</code> (reset cache) or <code>false</code>. If the attribute is bound to a view scoped backing bean,
  			care should be taken to reset the property back to false (e.g via a <code>PreRenderView</code> event on the next request, or
  			<code>CallbackPhaseListener</code> on the current request).
  		</p>
  		
  		<b>Programmatic reset</b>
  		<p>
  			Pressing the following button will reset the cache that's used in example 1 at the start of this page via the 
  			programmatic method. With this method the attribute <span style="white-space: nowrap">
  			<code>reset="\#{cacheBean.reset}"</code></span> is <b>NOT</b>
  			used.
  		</p>
  		<h:form>
			<h:commandButton action="#{cacheBean.resetProgrammatic}" value="Reset Example 1 cache programmatically" />
		</h:form>
		<br/>
  		
		<b>Reset via component attribute</b>
		<p>
  			Pressing the following button will reset the cache that's used in example 1 at the start of this page by setting
  			a bean property that's bound to the attribute <span style="white-space: nowrap">
  			<code>reset="\#{cacheBean.reset}"</code></span> on the 
  			component to <code>true</code>.
  		</p>
		<h:form>
			<h:commandButton action="#{cacheBean.resetAttribute}" value="Reset Example 1 cache via attribute" />
		</h:form>
		
		<hr/>
		<br/>
		
		<h3>Example 5 - Caching value expressions</h3>
  		<p>
  			Sometimes it might be convenient to cache an EL value expression instead or in addition of a fully rendered piece of markup.
  			This is especially useful for a postback, since after a postback JSF (of course) won't evaluate the cached markup, but will
  			evaluate value expressions again.
  		</p>
  		
  		<b>Without o:cacheValue</b>
  		<p>
  			Clicking on any of the 'Postback' buttons below will cause a new date to be generated at each click, instead
  			of the actually selected date. This is because JSF doesn't send the actual row data along, but merely a row number.
  			Because the backing bean is request scoped and the expression <code>\#{cacheBean.items}</code> is evaluated 
  			fresh after each postback, we'll end up selecting a new date each time.
  		</p>
  		<h:form>
  			<p>
  				Item: #{empty cacheBean.item? '(none)' : cacheBean.item}
  			</p>
  			<o:cache>
				<h:dataTable value="#{cacheBean.items}" var="item">
					<h:column>
						<i>#{item}</i>
					</h:column>
					<h:column>
						<h:commandButton value="Postback" action="#{cacheBean.saveItem(item)}" >
							<f:ajax execute="@form" render="@form" />
						</h:commandButton>
					</h:column>
				</h:dataTable>
			</o:cache>
  		</h:form>
  		<br/>
  		
		<b>With o:cacheValue</b>
		<p>
  			The following example makes use of <code>o:cacheValue</code> to cache the value expression as well. Clicking
  			any of the 'Postback' buttons in the example below will cause the same date to be selected as the one in the row
  			where the button is clicked.
		</p>
		<h:form>
			<p>
				Item: #{empty cacheBean.item? '(none)' : cacheBean.item}
			</p>
			<o:cache>
				<o:cacheValue name="items" value="#{cacheBean.items}"/>
  				
				<h:dataTable value="#{items}" var="item">
					<h:column>
						<i>#{item}</i>
					</h:column>
					<h:column>
						<h:commandButton value="Postback" action="#{cacheBean.saveItem(item)}" >
							<f:ajax execute="@form" render="@form" />
						</h:commandButton>
					</h:column> 
				</h:dataTable>
			</o:cache>
  		</h:form>
  		
	</ui:define>
</ui:composition>